# -*- coding: utf-8 -*-
import json
from collections import OrderedDict

import requests
from django.conf import settings

from async import async_job
from common.channel.base_pay import BasePay, SignMd5
from common.order.db import get_pay, add_pay_success
from common.utils import track_logging
from common.utils.exceptions import SignError

_LOGGER = track_logging.getLogger(__name__)

APP_CONF = {
    # 正式商户
    '010190723101527686460': {
        'API_KEY': 'dSQIo71QHY0ZdkHvPqJ5',
    },
    'gateway': 'http://47.94.4.210/trade_api/order/pay.do',
    'query_gateway': 'http://47.94.4.210/trade_api/query/order.do',
}

PAY_TYPE_DICT = {
    'cloud_flash': '1103',  # 云闪付
}


class HanYinPay(BasePay, SignMd5):

    # 异步回调签名验证
    def verify_notify_sign(self, parameter, key):

        pending_str = self.pending_str(parameter, key, not_sign=['sign'])
        sign = parameter['sign']
        calculated_sign = self.md5_sign_upper(pending_str)
        if sign != calculated_sign:
            _LOGGER.info("hanyinpay sign: %s, calculated sign: %s", sign, calculated_sign)
            raise SignError('sign not pass, data: %s' % parameter)

    # 下单
    def create_charge(self, pay, pay_amount, info):
        app_id = info['app_id']
        service = info.get('service')
        api_key = self.get_api_key(APP_CONF, app_id)

        parameter_dict = OrderedDict((
            ('orderId', str(pay.id)),  # 商户订单号
            ('merchantId', app_id),  # 商户ID
            ('version', '0.0.1'),  # 版本号
            ('orderAmt', '%.f' % (float(pay_amount) * 100)),  # 订单金额 分
            ('bizCode', self.get_pay_type(service, PAY_TYPE_DICT)),  # 业务代码
            ('type', self.get_pay_type(service, PAY_TYPE_DICT)),  # 银行类型
            ('returnUrl', '{}/pay/api/{}/new/hanyinpay/'.format(
                settings.NOTIFY_PREFIX, settings.RETURN_PATH)),
            ('bgUrl', '{}/pay/api/{}/new/hanyinpay/{}'.format(
                settings.NOTIFY_PREFIX, settings.NOTIFY_PATH, app_id)),
            ('terminalIp', self.get_device_ip(info)),  # 客户端ip
            ('productName', 'none'),  # 商品名称
            ('productDes', 'none'),  # 商品描述
            ('bankCode', ''),  # 银行代码
            ('cardType', ''),  # 银行卡类型
            ('accountNo', ''),  # 银行卡号
        ))
        # 待签名字符串
        pending_str = self.pending_str(parameter_dict, api_key)
        parameter_dict['sign'] = self.md5_sign_upper(pending_str)

        json_parameter = json.dumps(parameter_dict)
        _LOGGER.info("hanyinpay create date: %s, order_id is: %s", json_parameter,
                     parameter_dict['orderId'])

        headers = {'Content-Type': 'application/x-www-form-urlencoded'}
        response = requests.post(self.get_gateway(APP_CONF), data=parameter_dict, headers=headers, timeout=5)
        data = json.loads(response.text)
        if data['rspCode'] != '00':
            return {'charge_info': data['rspMsg']}
        url = data['payUrl']
        _LOGGER.info('hanyinpay pay url: %s', url)
        return {'charge_info': url}

    # success异步回调
    def check_notify_sign(self, request, app_id):
        _LOGGER.info("hanyinpay notify body: %s", request.body)
        data = json.loads(request.body)
        _LOGGER.info("hanyinpay notify data: %s, order_id is: %s", data, data['orderId'])
        self.verify_notify_sign(data, self.get_api_key(APP_CONF, app_id))
        pay_id = data['orderId']
        pay = self.check_ip_pay_status(request, pay_id, channel_name='hanyinpay', data=data)
        if not pay:
            return 'ok'

        mch_id = pay.mch_id
        trade_status = str(data['status'])
        trade_no = data['orderId']
        total_fee = float(data['orderAmt']) / 100.0
        extend = {
            'trade_status': trade_status,
            'trade_no': trade_no,
            'total_fee': total_fee,
        }
        if trade_status == '00':
            self.check_channel_order(pay_id, total_fee, app_id)
            _LOGGER.info('hanyinpay check order success, user_id:%s pay_id:%s' % (mch_id, pay_id))
            add_pay_success(mch_id, pay_id, total_fee, trade_no, extend)
            # async notify
            async_job.notify_mch(pay_id)
            return 'ok'

    # 订单查询
    def query_charge(self, pay_order, app_id):
        pay_id = pay_order.id
        api_key = self.get_api_key(APP_CONF, app_id)
        pay = get_pay(pay_id)
        parameter_dict = OrderedDict((
            ('orderId', str(pay.id)),  # 商户订单号
            ('merchantId', app_id),  # 商户ID
            ('bizCode', '4001'),  # 业务代码
            ('version', '0.0.1'),  # 版本号
        ))
        # 待签名字符串
        pending_str = self.pending_str(parameter_dict, api_key)
        parameter_dict['sign'] = self.md5_sign_upper(pending_str)

        _LOGGER.info('hanyinpay query data %s, order_id is: %s', json.dumps(parameter_dict),
                     parameter_dict['orderId'])
        headers = {'Content-Type': 'application/x-www-form-urlencoded'}
        response = requests.post(self.get_query_geteway(APP_CONF), data=parameter_dict, headers=headers, timeout=5)
        data = json.loads(response.text)
        _LOGGER.info('hanyinpay query rsp, %s', data)
        if data['rspCode'] == '00':
            trade_status = data['status']
            total_fee = float(data.get('orderAmt')) / 100.0
            trade_no = str(data['orderId'])
            extend = {
                'trade_status': trade_status,
                'trade_no': trade_no,
                'total_fee': total_fee,
            }
            if trade_status == '00':
                self.check_channel_order(pay_id, total_fee, app_id)
                _LOGGER.info('hanyinpay query order success, mch_id:%s pay_id:%s' % (pay_order.mch_id, pay_id))
                add_pay_success(pay_order.mch_id, pay_id, total_fee, trade_no, extend)
                async_job.notify_mch(pay_order.id)
            else:
                _LOGGER.info('hanyinpay query order success,but not pay success,msg:%s ' % data['rspMsg'])
        else:
            _LOGGER.warn('hanyinpay data error, msg: %s', data['rspMsg'])


def create_charge(pay, pay_amount, info):
    return HanYinPay().create_charge(pay, pay_amount, info)


def check_notify_sign(request, app_id):
    return HanYinPay().check_notify_sign(request, app_id)


def query_charge(pay_order, app_id):
    HanYinPay().query_charge(pay_order, app_id)
